#ifndef _TERRAIN_H
#define _TERRAIN_H

#include "Ogre.h"
#include "ETTerrainManager.h"
#include "ETTerrainInfo.h"
#include "ETBrush.h"
#include "ETSplattingManager.h"
#include <vector>
#include "GameSystemManager.h"
#include "OgreSystem.h"
#include "GameSceneManager.h"
#include "Decal.h"

//#include "GameSystem.h"

using namespace Ogre;
using namespace ET;
using namespace std;

class ET::TerrainManager;
class ET::Brush;
class ET::TerrainInfo;

class GameSystemManager;
class GameSceneManager;
class ET::TerrainManager;
class OgreSystem;
//class GameSystem;


//Config structure of the Terrain System
struct TerrainConfig {

	bool mIsTerrainLoaded;

	//The size of the terrain to be rendered
	float mTerrainSizeX;
	float mTerrainSizeY;
	float mTerrainSizeZ;
	
	//The size of the heightmap image
	string mHeightmapFileName;
	unsigned int mHeightmapHeight;
	unsigned int mHeightmapWidth;

	string mTerrainBrushImage;
	ushort mTerrainBrushWidth;
	ushort mTerrainBrushHeight;
	float mTerrainBrushIntensity;

	//The size of the splatting textures
	string mSplatTextureName;
	float mSplatTextureHeight;
	float mSplatTextureWidth;
	unsigned int mMaxSplattingTextures;
	unsigned int mCurrentSplattingTextures;

	uint mChosenTexture;
	
	string mPaintBrushImage;
	ushort mPaintBrushWidth;
	ushort mPaintBrushHeight;
	float mPaintBrushIntensity;

	//The size of the lightmap
	float mLightmapHeight;
	float mLightmapWidth;

	unsigned int mLODErrorMargin;
	bool mLODMorphing;
	float mLODMorphFactor;
	string mCursorMesh ;
};
extern TerrainConfig terrain_config;


class TerrainSystem {
public: 

	TerrainSystem();
	~TerrainSystem();

	void registerParams();
	void init();
	void setup();
	void update();
	void destroy();

	void resetParameters();
	void saveAttrib(TiXmlElement* pAttrib);
	//void saveSettings(std::string mFileName);
	void setAttribute(std::string name,std::string value);

	void loadTerrain();
	void createETM();
	void generateTerrain();
	void updateLightmap();
	void setMapSize(Ogre::Vector3 mapSize);
	void updateBrush(const OIS::MouseEvent &evt); //Ogre::Real screenX,Ogre::Real screenY
	void paint();
	void removeTerrain();
	void setTerrainEditBrush(unsigned short size);
	void setPaintEditBrush(unsigned short size);
	void setTerrainEditBrushIntensity(float size);
	void setPaintEditBrushIntensity(float size);
	void addTexture(const std::string name);
	void removeTexture(const std::string name);
	void TerrainSystem::searchDiskForTextures();
	void mouseButtonDownNotification(bool controledByGui,unsigned int button);
	void mouseButtonUpNotification(bool controledByGui,unsigned int button);
	Ogre::Real getTerrainHeightAt(Real x,Real z);

	Ogre::Vector3 rayIntersectsTerrain();

	static bool enablePainting;
	static bool riseTerrain;
	static bool paintTerrain;
	static bool smoothTerrain;
	static ET::TerrainManager* getTerrainManager();

	static Ogre::SceneNode *mPointer;
	static std::string textureList[6];

	static DecalCursor *mPincelDecal;

	//unsigned short m
	
	
	
	void saveTerrain(std::string mFileName);
	bool saveToXML();

	////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Tweakeable parameters, must register these via GameSystem->registerParam
	/*
	bool mIsTerrainLoaded; // (new bool = false);
	float mTerrainSizeX;
	float mTerrainSizeY;
	float mTerrainSizeZ;

	//static 
	static string mHeightmapFileName;
	unsigned int mHeightmapHeight;
	unsigned int mHeightmapWidth;

	string mTerrainBrushImage;
	unsigned int mTerrainBrushWidth;
	unsigned int mTerrainBrushHeight;
	float mTerrainBrushIntensity;

	//The size of the splatting textures
	string mSplatTextureName;
	float mSplatTextureHeight;
	float mSplatTextureWidth;
	unsigned int mMaxSplattingTextures;
	unsigned int mCurrentSplattingTextures;

	unsigned int mChosenTexture;

	string mPaintBrushImage;
	unsigned int mPaintBrushWidth;
	unsigned int mPaintBrushHeight;
	float mPaintBrushIntensity;

	float mLightmapHeight;
	float mLightmapWidth;

	unsigned int mLODErrorMargin;
	bool mLODMorphing;
	float mLODMorphFactor;
	string mCursorMesh ;
	*/
	////////////////////////////////////////////////////////////////////////////////////////////////////////////


private:
	static ET::TerrainManager* mTerrainMgr;
    static ET::SplattingManager* mSplatMgr;
	static const ET::TerrainInfo* mTerrainInfo;
	
	ET::Brush averageFilter(int x, int z, ET::Brush shape, float fIntensity);

	static Ogre::Image terrainBrushImage;
	static Ogre::Image paintBrushImage;

    static ET::Brush mEditBrush;
    static bool mDeform;
	
	Ogre::TexturePtr lightmapTex;
	
};

#endif